using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Xml.Xsl;
using System.IO;

using System.Data;

using Pampa.Grid.Utils;

using Pampa.Grid.Core;
using Pampa.Grid.Data;
using Pampa.Grid.UI.Exceptions;
using Pampa.Grid.Exceptions;
using Pampa.Grid.Core.Filters;

using Pampa.WebControls;

using Pampa.CRUD.Core;
using Pampa.CRUD.Configuration;

namespace Pampa.Grid.UI.CustomControls
{
    [DesignerAttribute(typeof(BaseDesigner), typeof(System.ComponentModel.Design.IDesigner))]
    public class FilterManager : BaseControl
    {
        private string gridID;
        private int filterCount;
        private string pathImages;
        private CustomGrid customGrid;

        public FilterManager()
        {
            this.CssClass = "filterManagerDefault";
            this.PathImages = "Pampa.WebControls" + GetImagesPath();
        }

        #region Properties

        public string GridID
        {
            get { return gridID; }
            set { gridID = value; }
        }

        public string PathImages
        {
            get { return pathImages; }
            set { pathImages = value; }
        }

        public CustomGrid Grid
        {
            get
            {
                if (customGrid == null && this.Page != null)
                {
                    customGrid = (CustomGrid)Page.FindControl(this.GridID);
                }

                if (customGrid == null)
                {
                    throw (new CustomGridException("QuickFiltersPanel Error. There is no CustomGrid associated to the panel.'"));
                }

                return customGrid;
            }
            set
            {
                customGrid = value;
                this.GridID = customGrid.ID;
            }
        }

        #endregion

        #region Load

        protected override void OnLoad(EventArgs e)
        {
            Ajax.Utility.RegisterTypeForAjax(typeof(FilterManager));

            if (this.CssClass == "filterManagerDefault")
                RegisterStyleSheet("Pampa.Grid/FilterManager.css");

            RegisterLibrary("Pampa.Common/Common.js");
            RegisterLibrary("Pampa.Common/TextButton.js");

            RegisterLibrary("Pampa.Grid/FilterManager.js");
            RegisterLibrary("Pampa.Grid/Filter.js");

            RegisterLibrary("Pampa.CRUD/ItemsCommon.js");

            base.OnLoad(e);
        }

        #endregion

        #region Render

        protected override void Render(HtmlTextWriter writer)
        {
            writer.AddAttribute("id", this.ID);
            writer.AddAttribute("class", this.CssClass);

            if (!string.IsNullOrEmpty(this.Height.ToString()))
                writer.AddStyleAttribute("height", this.Height.ToString());
            if (!string.IsNullOrEmpty(this.Width.ToString()))
                writer.AddStyleAttribute("width", this.Width.ToString());

            writer.RenderBeginTag(HtmlTextWriterTag.Div);

            if (this.Grid == null)
            {
                writer.WriteLine("There is no grid called " + this.GridID);
                writer.RenderEndTag();
            }
            else if (!this.Grid.Configuration.Configurable)
            {
                writer.WriteLine(this.Grid.Configuration.NoConfigurableMessage);
                writer.RenderEndTag();
            }
            else
            {
                writer.RenderEndTag();
                RenderItemsReferenceControls(writer);
                RenderDefinitions(writer);
            }
        }

        private void RenderItemsReferenceControls(HtmlTextWriter output)
        {
            output.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");
            output.RenderBeginTag(HtmlTextWriterTag.Div);

            foreach (MainFilterGroupDefinition mainFilterGroup in this.Grid.MainFilterGroupDefinitions)
            {
                foreach (MainFilterDefinition mainFilterDef in mainFilterGroup.Items)
                {
                    mainFilterDef.Item.Control.ID = "ref_" + mainFilterGroup.Id + "_" + mainFilterDef.Item.Id;
                    mainFilterDef.Item.Control.RenderControl(output);
                }
            }

            output.RenderEndTag();
        }

        private void RenderDefinitions(HtmlTextWriter output)
        {
            output.WriteLine("<script type=\"text/javascript\">");
            output.WriteLine("var obj" + this.ID + " = new WebFilterManager('" + this.ID + "', '" + this.GridID + "');");
            output.WriteLine(" ");

            RenderFieldsDefinition(output);
            RenderOperationsDefinition(output);
            RenderMainFilterDefinition(output);

            output.WriteLine("obj" + this.ID + ".andText = '" + Resources.ConfigManager.AndText + "';");
            output.WriteLine("obj" + this.ID + ".orText = '" + Resources.ConfigManager.OrText + "';");
            output.WriteLine("obj" + this.ID + ".addConditionText = '" + Resources.ConfigManager.AddCondition + "';");
            output.WriteLine("obj" + this.ID + ".addGroupText = '" + Resources.ConfigManager.AddGroup + "';");
            output.WriteLine("obj" + this.ID + ".removeGroupText = '" + Resources.ConfigManager.RemoveGroup + "';");
            output.WriteLine("obj" + this.ID + ".pathimages = '" + GetResourceUrl(this.PathImages) + "';");
            output.WriteLine("obj" + this.ID + ".show('" + this.ID + "');");

            output.WriteLine("</script>");
        }

        private void RenderFieldsDefinition(HtmlTextWriter output)
        {
            foreach (MainFilterGroupDefinition mainFilterGroup in this.Grid.MainFilterGroupDefinitions)
            {
                output.WriteLine("obj" + this.ID + ".addFieldGroup('" + mainFilterGroup.Id + "', '" + mainFilterGroup.Label + "', '" + mainFilterGroup.Join + "');");

                foreach (MainFilterDefinition filterDef in mainFilterGroup.Items)
                {
                    output.WriteLine("obj" + this.ID + ".addField('" + filterDef.Item.Id + "','" + filterDef.Item.Label + "'," + (int)filterDef.Item.ItemType + ",'" + filterDef.ValueType.AssemblyQualifiedName + "','" + mainFilterGroup.Id + "');");
                }
            }
        }

        private void RenderOperationsDefinition(HtmlTextWriter output)
        {
            foreach (MainFilterGroupDefinition mainFilterGroup in this.Grid.MainFilterGroupDefinitions)
            {
                foreach (MainFilterDefinition filterDef in mainFilterGroup.Items)
                {
                    RenderOperationsDefinitionType(output, filterDef.ValueType);
                }
            }

            output.WriteLine(" ");
        }

        private void RenderOperationsDefinitionType(HtmlTextWriter output, Type type)
        {
            IList<OperationType> ops = TypesHelper.GetAllowableOperations(type);

            foreach (OperationType op in ops)
            {
                string operationType = Enum.GetName(typeof(OperationType), op);
                string operationDescription = TypesHelper.GetOperationTypeDescription(op);

                output.WriteLine("obj" + this.ID + ".addOperation('" + type.AssemblyQualifiedName + "', '" + operationType + "', '" + operationDescription + "');");
            }

            output.WriteLine(" ");
        }

        private void RenderMainFilterDefinition(HtmlTextWriter output)
        {
            if (this.Grid.Configuration.MainFilter != null)
            {
                string nexo;

                if (this.Grid.Configuration.MainFilter is OrGroupFilter)
                    nexo = "OR";
                else
                    nexo = "AND";

                output.WriteLine("obj" + this.ID + ".mainFilter.nexo = \"" + nexo + "\";");

                foreach(Filter filter in this.Grid.Configuration.MainFilter.InnerFilters)
                {
                    RenderFilterDefinition(filter, output, "mainFilter");
                }
            }
        }
        
        private void RenderFilterDefinition(Filter filter, HtmlTextWriter output, string idparentfilter) 
        {
            if (filter is SimpleFilter)
            {
                SimpleFilter simpleFilter = ((SimpleFilter)filter);

                string field = simpleFilter.Field;
                string operation = Enum.GetName(typeof(OperationType), simpleFilter.Operation);
                string value = simpleFilter.Value.ToString();
                string typeValue = simpleFilter.Value.GetType().FullName;

                output.WriteLine("obj" + this.ID + ".addConditionFilter('" + idparentfilter + "', '" + field + "', '" +
                                 operation + "','" + value + "','" + typeValue + "');");

            }
            else 
            {
                GroupFilter groupFilter = ((GroupFilter)filter);

                string nexo = (groupFilter is OrGroupFilter) ? "OR" : "AND";
                string newIdFilter = "idfilter" + (filterCount++).ToString();

                output.WriteLine("var " + newIdFilter + " = obj" + this.ID + ".addGroupFilter('" + idparentfilter + "', '" + nexo + "', '" + groupFilter.Join + "');");

                foreach (Filter innerFilter in groupFilter.InnerFilters)
                {
                    RenderFilterDefinition(innerFilter, output, newIdFilter);
                }
                output.WriteLine(" ");
            }
        }

        #endregion

        #region Ajax Functions

        [Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
        public static string GetDescription(string entityTypeQualifiedName, string strValue)
        {
            Type entityType = Type.GetType(entityTypeQualifiedName);
            object value = EntityManager.GetValueFromString(entityType, strValue);

            if (value is IIdDescription)
                return ((IIdDescription)value).Description;
            else
                return "";
        }

        #endregion
    }
}